package io.gitee.zhangbinhub.acp.boot.tools

import io.gitee.zhangbinhub.acp.core.common.CommonTools
import io.gitee.zhangbinhub.acp.core.common.log.LogFactory
import jakarta.servlet.ServletInputStream
import jakarta.servlet.http.HttpServletRequest
import org.springframework.util.LinkedMultiValueMap
import org.springframework.util.MultiValueMap
import java.io.IOException
import java.net.URI
import java.net.URLDecoder
import java.net.URLEncoder

/**
 * Http请求相关工具类
 */
object HttpTools {

    private val log = LogFactory.getInstance(HttpTools::class.java)// 日志对象

    /**
     * 通过request获取项目webRoot路径
     *
     * @return 项目webRoot路径
     */
    @JvmStatic
    fun getWebRootPath(request: HttpServletRequest): String {
        val webRoot = request.contextPath
        return if (webRoot == "/") {
            ""
        } else {
            webRoot
        }
    }

    /**
     * url编码
     *
     * @param url      url字符串
     * @param encoding 字符编码
     * @return 结果字符串
     */
    @JvmStatic
    @JvmOverloads
    fun urlEncoding(url: String, encoding: String = CommonTools.getDefaultCharsetName()): String =
        try {
            URLEncoder.encode(url, encoding)
        } catch (e: Exception) {
            log.error(e.message, e)
            url
        }

    /**
     * url解码
     *
     * @param url      url字符串
     * @param encoding 字符编码
     * @return 结果字符串
     */
    @JvmStatic
    @JvmOverloads
    fun urlDecoding(url: String, encoding: String = CommonTools.getDefaultCharsetName()): String =
        try {
            URLDecoder.decode(url, encoding)
        } catch (e: Exception) {
            log.error(e.message, e)
            url
        }

    /**
     * 获取客户端发送的内容（xml或json）字符串
     *
     * @param request 请求对象
     * @return 请求内容
     */
    @JvmStatic
    fun getRequestContent(request: HttpServletRequest): String {
        var sis: ServletInputStream? = null
        try {
            sis = request.inputStream
            val size = request.contentLength
            if (size <= 0) {
                return ""
            }
            val buffer = ByteArray(size)
            val dataByte = ByteArray(size)
            var count = 0
            var rbyte: Int
            while (count < size) {
                rbyte = sis!!.read(buffer)
                if (rbyte > 0) {
                    System.arraycopy(buffer, 0, dataByte, count, rbyte)
                    count += rbyte
                } else {
                    break
                }
            }
            return if (count <= 0) {
                ""
            } else String(dataByte, charset(request.characterEncoding))
        } catch (e: IOException) {
            log.error(e.message, e)
            return ""
        } finally {
            if (sis != null) {
                try {
                    sis.close()
                } catch (e: IOException) {
                    log.error(e.message, e)
                }

            }
        }
    }

    /**
     * uri是否被识别
     *
     * @param uri   请求url字符串
     * @param regex 正则表达式
     * @return true|false
     */
    @JvmStatic
    fun isBeIdentifiedUri(uri: String, regex: String): Boolean {
        return CommonTools.regexPattern(regex, uri)
    }

    @JvmStatic
    @JvmOverloads
    fun getPathVariable(uri: URI?, variableIndex: Int? = null): String? =
        uri?.path?.split("/")?.let { pathList ->
            if (variableIndex != null) {
                if (pathList.size > variableIndex) {
                    pathList[variableIndex]
                } else {
                    null
                }
            } else {
                pathList[pathList.lastIndex]
            }
        }

    @JvmStatic
    fun getQueryVariable(uri: URI?, variableKey: String): String? = getQueryMap(uri).getFirst(variableKey)

    @JvmStatic
    fun getQueryMap(uri: URI?): MultiValueMap<String, String> = LinkedMultiValueMap<String, String>().apply {
        uri?.query?.split("&")?.forEach { item ->
            val list = item.split("=")
            if (list.size == 2) {
                this.add(list[0], list[1])
            }
        }
    }
}
